﻿Imports System.Windows
Imports CommunityToolkit.Mvvm.ComponentModel
Imports CommunityToolkit.Mvvm.Input

Public Class BlogItemViewModel : Inherits ObservableObject

    Private _blog As Blog
    Public Property Blog As Blog
        Get
            Return _blog
        End Get
        Set(value As Blog)
            SetProperty(_blog, value)
            BlogPostDateString = value.PostDate.ToString("yyyy-MM-dd")
        End Set
    End Property

    Private _blogPostDateString As String
    Public Property BlogPostDateString As String
        Get
            Return _blogPostDateString
        End Get
        Set(value As String)
            SetProperty(_blogPostDateString, value)
        End Set
    End Property

    Private _upvoteButtonText As String
    Public Property UpvoteButtonText As String
        Get
            Return _upvoteButtonText
        End Get
        Set(value As String)
            SetProperty(_upvoteButtonText, value)
        End Set
    End Property

    Private _downvoteButtonText As String
    Public Property DownvoteButtonText As String
        Get
            Return _downvoteButtonText
        End Get
        Set(value As String)
            SetProperty(_downvoteButtonText, value)
        End Set
    End Property

    Private _song As Song
    Public Property Song As Song
        Get
            Return _song
        End Get
        Set(value As Song)
            SetProperty(_song, value)
        End Set
    End Property

    Private _songSource As Uri
    Public Property SongSource As Uri
        Get
            Return _songSource
        End Get
        Set(value As Uri)
            SetProperty(_songSource, value)
        End Set
    End Property

    Private _songPlayStatus As String
    Public Property SongPlayStatus As String
        Get
            Return _songPlayStatus
        End Get
        Set(value As String)
            SetProperty(_songPlayStatus, value)
        End Set
    End Property

    Private ReadOnly _client As HttpClientBase

    'Public ReadOnly Property ChangePlayStatusCommand As New RelayCommand(AddressOf ChangePlayStatusClicked)
    Public ReadOnly Property FollowUserCommand As New AsyncRelayCommand(AddressOf FollowUserClicked)
    Public ReadOnly Property UpvoteCommand As New AsyncRelayCommand(AddressOf UpvoteClicked)
    Public ReadOnly Property DownvoteCommand As New AsyncRelayCommand(AddressOf DownvoteClicked)

    Public Sub New()
        _client = New HttpClientBase()
        Call PickBlog()
    End Sub

    Private Async Function GetSonginfo() As Task
        Try
            Console.WriteLine("songKeyword: " + Blog.SongKeyword)
            Console.WriteLine("songID: " + Blog.SongID)
            '调用服务器获取歌曲信息
            Song = Nothing
            SongSource = Nothing
            Dim response = Await _client.GetAsync(Of Song)(String.Format("vdm/api/music/song/{0}/{1}", Blog.SongKeyword, Blog.SongID))
            If response.Code = 200 Then
                Song = response.Data
                Dim sourceUrl As String = Song.SongUrl
                Dim mp3Index As Integer = sourceUrl.LastIndexOf(".mp3")
                If mp3Index <> -1 Then
                    ' 只保留 ".mp3" 及之前的内容
                    sourceUrl = sourceUrl.Substring(0, mp3Index + 4)        ' +4 是为了包含 ".mp3" 本身
                End If
                SongSource = New Uri(sourceUrl, UriKind.Absolute)
            Else
                MessageBox.Show("获取歌曲信息失败：" & response.Message)
            End If
            '设置歌曲信息
            If Song IsNot Nothing Then
                Me.SongPlayStatus = "播放中"
            Else
                Song = New Song With {
                   .Keyword = "",
                   .Id = -1,
                   .Title = "无法获取歌曲信息",
                   .Artist = "无法获取歌手信息"
                }
                Me.SongPlayStatus = "无法播放"
            End If
        Catch ex As Exception
            Console.WriteLine(ex.Message)
            Console.WriteLine(ex.StackTrace)
            MessageBox.Show("系统错误：" & ex.Message)
            NavigationService.Navigate(NavigationData.LOGIN_PAGE_URI)
        End Try
    End Function

    Private Async Function PickBlog() As Task
        ' 调用服务器获取 Blog 数据
        Try
            Dim response = Await _client.GetAsync(Of Blog)("vdm/api/blog/pickBlog")
            Blog = response.Data
            '判断获取到的 Blog 是否为空
            If Blog Is Nothing Then
                Me.Blog = New Blog With {
                    .Id = -1,
                    .Content = "错误信息：" & response.Message,
                    .Author = "UNKNOWN",
                    .UpVotes = 0,
                    .DownVotes = 0,
                    .PostDate = Date.Now,
                    .SongID = -1
                }
                Me.SongPlayStatus = "无法播放"
                MessageBox.Show("获取漂流瓶失败，请稍后再试")
                Me.UpvoteButtonText = $"无法点赞"
                Me.DownvoteButtonText = $"无法反对"
                Return
            End If
            Me.UpvoteButtonText = $"点赞 ({Blog.UpVotes})"
            Me.DownvoteButtonText = $"反对 ({Blog.DownVotes})"
            Call GetSonginfo()
        Catch ex As Exception
            MessageBox.Show("系统错误：" & ex.Message)
            Console.WriteLine(ex.Message)
            NavigationService.Navigate(NavigationData.LOGIN_PAGE_URI)
        End Try
    End Function

    Private Async Function FollowUserClicked() As Task
        ' 先判断作者是不是用户本人
        If Blog.Author = Application.Current.Resources("UserName").ToString() Then
            MessageBox.Show("不能关注自己")
            Return
        End If
        ' 先调用服务器从作者的用户名获取用户 ID
        Try
            Dim res1 = Await _client.GetAsync(Of User)(String.Format("vdm/api/account/findUser/name/{0}", Blog.Author))
            If res1.Code <> 200 Then
                MessageBox.Show("获取作者的信息失败：" & res1.Message)
                Return
            End If
            ' 调用服务器关注用户
            Dim authorId As Integer = res1.Data.Id
            ' 判断当前用户是否已经关注了作者
            Dim res2 = Await _client.GetAsync(Of Boolean)(String.Format("vdm/api/following/check/{0}/{1}", Application.Current.Resources("UserId").ToString(), authorId))
            If res2.Code <> 200 Then
                MessageBox.Show("获取关注状态失败：" & res2.Message)
                Return
            End If
            If res2.Data Then
                If MessageBox.Show("您已经关注了该用户，您是想要取消关注吗？", MessageBoxButton.OKCancel) = MessageBoxResult.OK Then
                    Await UnFollowUserLogic(authorId)
                    Return
                Else
                    Return
                End If
            End If
            ' 再调用服务器关注用户
            Dim followInfo As New FollowingUser With {
                .UserId = Application.Current.Resources("UserId").ToString(),
                .FollowingUserId = authorId
            }
            Dim res3 = Await _client.PostAsync(Of Boolean)(followInfo, "vdm/api/following/follow")
            If res3.Code <> 200 Then
                MessageBox.Show("关注用户失败：" & res3.Message)
                Return
            End If
            MessageBox.Show("已成功关注用户：" + Blog.Author)
        Catch ex As Exception
            Console.WriteLine(ex.Message)
            Console.WriteLine(ex.StackTrace)
            MessageBox.Show("系统错误：" & ex.Message)
            NavigationService.Navigate(NavigationData.LOGIN_PAGE_URI)
        End Try
    End Function

    Private Async Function UnFollowUserLogic(authorId As Integer) As Task
        Dim response = Await _client.DeleteAsync(Of Boolean)(
            String.Format("vdm/api/following/unfollow/{0}/{1}",
                          Application.Current.Resources("UserId").ToString(),
                          authorId.ToString()))
        If response.Code <> 200 Then
            MessageBox.Show("取消关注失败：" & response.Message)
            Return
        End If
        MessageBox.Show("已成功取消关注用户：" + Blog.Author)
    End Function

    Private Async Function UpvoteClicked() As Task
        If Blog.Id = -1 Then
            Return
        End If
        ' 先判断作者是不是用户本人
        If Blog.Author = Application.Current.Resources("UserName").ToString() Then
            MessageBox.Show("不能评价自己的漂流瓶")
            Return
        End If
        Try
            Dim voteStatus = Await VoteCheck()
            If voteStatus = 1 Then
                If MessageBox.Show("您已经点赞过了，是想要撤销之前的点赞吗？", MessageBoxButton.OKCancel) = MessageBoxResult.OK Then
                    '调用服务器撤销点赞
                    Dim res1 = Await _client.DeleteAsync(Of Boolean)(String.Format("vdm/api/vote/remove/{0}/{1}", Blog.Id, Application.Current.Resources("UserId").ToString()))
                    If res1.Code <> 200 OrElse Not res1.Data Then
                        MessageBox.Show("撤销点赞失败：" & res1.Message)
                        Return
                    End If
                    Me.Blog.UpVotes -= 1
                    '调用服务器更新 Blog 点赞数
                    Dim res2 = Await _client.PostAsync(Of Boolean)(Blog, "vdm/api/blog/editBlog")
                    If res2.Code <> 200 Then
                        MessageBox.Show("更新点赞数失败：" & res2.Message)
                        Return
                    End If
                    Me.UpvoteButtonText = $"点赞 ({Blog.UpVotes})"
                End If
            ElseIf voteStatus = -1 Then
                If MessageBox.Show("您已经反对过了，是想要更改为点赞吗？", MessageBoxButton.OKCancel) = MessageBoxResult.OK Then
                    '调用服务器更改投票
                    Dim res3 = Await _client.PostAsync(Of Boolean)(
                    New BlogVote With {.BlogID = Blog.Id, .UserID = Application.Current.Resources("UserId").ToString(), .VoteType = 1},
                    "vdm/api/vote/change")
                    If res3.Code <> 200 Then
                        MessageBox.Show("更改投票失败：" & res3.Message)
                        Return
                    End If
                    Me.Blog.UpVotes += 1
                    Me.Blog.DownVotes -= 1
                    '调用服务器更新 Blog 点赞数
                    Dim res4 = Await _client.PostAsync(Of Boolean)(Blog, "vdm/api/blog/editBlog")
                    If res4.Code <> 200 Then
                        MessageBox.Show("更新点赞数失败：" & res4.Message)
                        Return
                    End If
                    Me.UpvoteButtonText = $"点赞 ({Blog.UpVotes})"
                    Me.DownvoteButtonText = $"反对 ({Blog.DownVotes})"
                End If
            ElseIf voteStatus = 0 Then
                '调用服务器点赞
                Dim res5 = Await _client.PostAsync(Of Boolean)(
                New BlogVote With {.BlogID = Blog.Id, .UserID = Application.Current.Resources("UserId").ToString(), .VoteType = 1},
                "vdm/api/vote/vote")
                If res5.Code <> 200 Then
                    MessageBox.Show("点赞失败：" & res5.Message)
                    Return
                End If
                Me.Blog.UpVotes += 1
                '调用服务器更新 Blog 点赞数
                Dim res6 = Await _client.PostAsync(Of Boolean)(Blog, "vdm/api/blog/editBlog")
                If res6.Code <> 200 Then
                    MessageBox.Show("更新点赞数失败：" & res6.Message)
                    Return
                End If
                Me.UpvoteButtonText = $"点赞 ({Blog.UpVotes})"
            End If
        Catch ex As Exception
            MessageBox.Show("系统错误：" & ex.Message)
            Console.WriteLine(ex.Message)
            NavigationService.Navigate(NavigationData.LOGIN_PAGE_URI)
        End Try
    End Function

    Private Async Function DownvoteClicked() As Task
        If Blog.Id = -1 Then
            Return
        End If
        ' 先判断作者是不是用户本人
        If Blog.Author = Application.Current.Resources("UserName").ToString() Then
            MessageBox.Show("不能评价自己的漂流瓶")
            Return
        End If
        Try
            Dim voteStatus = Await VoteCheck()
            If voteStatus = -1 Then
                If MessageBox.Show("您已经反对过了，是想要撤销之前的反对吗？", MessageBoxButton.OKCancel) = MessageBoxResult.OK Then
                    '调用服务器撤销反对
                    Dim res1 = Await _client.DeleteAsync(Of Boolean)(String.Format("vdm/api/vote/remove/{0}/{1}", Blog.Id, Application.Current.Resources("UserId").ToString()))
                    If res1.Code <> 200 OrElse Not res1.Data Then
                        MessageBox.Show("撤销反对失败：" & res1.Message)
                        Return
                    End If
                    Me.Blog.DownVotes -= 1
                    '调用服务器更新 Blog 反对数
                    Dim res2 = Await _client.PostAsync(Of Boolean)(Blog, "vdm/api/blog/editBlog")
                    If res2.Code <> 200 Then
                        MessageBox.Show("更新反对数失败：" & res2.Message)
                        Return
                    End If
                    Me.DownvoteButtonText = $"反对 ({Blog.DownVotes})"
                End If
            ElseIf voteStatus = 1 Then
                If MessageBox.Show("您已经点赞过了，是想要更改为反对吗？", MessageBoxButton.OKCancel) = MessageBoxResult.OK Then
                    '调用服务器更改投票
                    Dim res3 = Await _client.PostAsync(Of Boolean)(
                        New BlogVote With {.BlogID = Blog.Id, .UserId = Application.Current.Resources("UserId").ToString(), .VoteType = -1},
                        "vdm/api/vote/change")
                    If res3.Code <> 200 Then
                        MessageBox.Show("更改投票失败：" & res3.Message)
                        Return
                    End If
                    Me.Blog.UpVotes -= 1
                    Me.Blog.DownVotes += 1
                    '调用服务器更新 Blog 点赞数
                    Dim res4 = Await _client.PostAsync(Of Boolean)(Blog, "vdm/api/blog/editBlog")
                    If res4.Code <> 200 Then
                        MessageBox.Show("更新点赞数失败：" & res4.Message)
                        Return
                    End If
                    Me.UpvoteButtonText = $"点赞 ({Blog.UpVotes})"
                    Me.DownvoteButtonText = $"反对 ({Blog.DownVotes})"
                End If
            ElseIf voteStatus = 0 Then
                '调用服务器反对
                Dim res5 = Await _client.PostAsync(Of Boolean)(
                    New BlogVote With {.BlogID = Blog.Id, .UserId = Application.Current.Resources("UserId").ToString(), .VoteType = -1},
                    "vdm/api/vote/vote")
                If res5.Code <> 200 Then
                    MessageBox.Show("反对失败：" & res5.Message)
                    Return
                End If
                Me.Blog.DownVotes += 1
                '调用服务器更新 Blog 反对数
                Dim res6 = Await _client.PostAsync(Of Boolean)(Blog, "vdm/api/blog/editBlog")
                If res6.Code <> 200 Then
                    MessageBox.Show("更新反对数失败：" & res6.Message)
                    Return
                End If
                Me.DownvoteButtonText = $"反对 ({Blog.DownVotes})"
            End If
        Catch ex As Exception
            MessageBox.Show("系统错误：" & ex.Message)
            Console.WriteLine(ex.Message)
            NavigationService.Navigate(NavigationData.LOGIN_PAGE_URI)
        End Try
    End Function

    Private Async Function VoteCheck() As Task(Of Integer)
        '查询点赞记录表
        Try
            Dim response = Await _client.GetAsync(Of Integer)(String.Format("vdm/api/vote/type/{0}/{1}", Blog.Id, Application.Current.Resources("UserId").ToString()))
            If response.Code = 200 Then
                Return response.Data
            Else
                MessageBox.Show("获取点赞信息失败：" & response.Message)
                Return -2
            End If
        Catch ex As Exception
            MessageBox.Show("系统错误：" & ex.Message)
            Console.WriteLine(ex.Message)
            NavigationService.Navigate(NavigationData.LOGIN_PAGE_URI)
            Return -2
        End Try
    End Function

    'Private Sub ChangePlayStatusClicked()
    '    If Me.SongPlayStatus = "无法播放" Then
    '        Exit Sub
    '    End If
    '    If Me.SongPlayStatus = "暂停" Then
    '        _musicPlayer.SongPause()
    '        Me.SongPlayStatus = "播放"
    '    Else
    '        _musicPlayer.SongPlay()
    '        Me.SongPlayStatus = "暂停"
    '    End If
    'End Sub

    'Private Function CanUpvoteCommand() As Boolean
    '    Return Blog.Id > -1
    'End Function

    'Private Function CanDownvoteCommand() As Boolean
    '    Return Blog.Id > -1
    'End Function

End Class
